﻿using System.Net.Sockets;
using Devonline.Communication.Abstractions;
using Devonline.Core;
using Microsoft.Extensions.Logging;
using NModbus;

namespace Devonline.Communication.Modbus;

/// <summary>
/// Modbus TCP 协议基类实现
/// </summary>
public class ModbusTCPCommunicator : ModbusCommunicator, IModbusCommunicator, IStreamCommunicator
{
    protected readonly Endpoint _tcpEndpoint;
    protected TcpClient? _tcpClient;

    public ModbusTCPCommunicator(ILogger<Communicator<byte[]>> logger, IModbusOptions options, Endpoint tcpEndpoint) : base(logger, options)
    {
        _tcpEndpoint = tcpEndpoint;
    }

    /// <summary>
    /// 当前连接状态
    /// </summary>
    public override bool IsConnected => _tcpClient?.Connected ?? false;
    /// <summary>
    /// 停止 Modbus TCP 通讯
    /// </summary>
    /// <returns></returns>
    public override async Task StopAsync()
    {
        _tcpClient?.Close();
        _tcpClient?.Dispose();
        _modbusMaster?.Dispose();
        await base.StopAsync();
    }
    /// <summary>
    /// 暂不实现发送数据的方法
    /// </summary>
    /// <param name="t"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public override Task SendAsync(byte[] t)
    {
        throw new NotImplementedException();
    }
    /// <summary>
    /// 打开 TCP 连接, 建立 Modbus 通讯
    /// </summary>
    /// <returns></returns>
    protected override Task OpenAsync()
    {
        if (IsRunning && !IsConnected)
        {
            ArgumentNullException.ThrowIfNull(_tcpEndpoint.Host);
            ArgumentNullException.ThrowIfNull(_tcpEndpoint.Port);
            _logger.LogDebug(LOG_COMMUNICATOR + " will connect to the: {host}:{port}", _options, _tcpEndpoint.Host, _tcpEndpoint.Port);
            _tcpClient = new TcpClient(_tcpEndpoint.Host, _tcpEndpoint.Port.Value);
        }

        if (IsRunning && IsConnected)
        {
            _logger.LogDebug(LOG_COMMUNICATOR + " will create the Modbus master", _options);
            _modbusMaster = new ModbusFactory().CreateMaster(_tcpClient);
        }

        return Task.CompletedTask;
    }
}